package cn.iclass.common.exception;

import cn.iclass.common.utils.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpStatus;
import org.apache.shiro.authz.AuthorizationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.util.List;

/**
 * @Description: 异常处理器
 * @author: alan
 * @date: 2019/6/10 5:34 PM
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

	/**
	 * 自定义异常
	 *
	 * @param e
	 * @return cn.iclass.common.utils.R
	 * @author alan
	 * @date 2019/6/10 5:35 PM
	 */
	@ExceptionHandler(GlobalException.class)
	public Result handleGlobalException(GlobalException e) {
		Result result = Result.error(e.getCode(), e.getMsg());
		return result;
	}

	/**
	 * 路径不存在
	 *
	 * @param e
	 * @return cn.iclass.common.utils.R
	 * @author alan
	 * @date 2019/6/10 4:55 PM
	 */
	@ExceptionHandler(NoHandlerFoundException.class)
	public Result handlerNoFoundException(Exception e) {
		log.warn("路径不存在:{}", e.getMessage());
		return Result.error(HttpStatus.SC_NOT_FOUND, "路径不存在，请检查路径是否正确");
	}

	/**
	 * 记录重复
	 *
	 * @param e
	 * @return cn.iclass.common.utils.R
	 * @author alan
	 * @date 2019/6/10 5:34 PM
	 */
	@ExceptionHandler(DuplicateKeyException.class)
	public Result handleDuplicateKeyException(DuplicateKeyException e) {
		log.warn("数据库中已存在该记录:{}", e.getMessage());
		return Result.error(HttpStatus.SC_BAD_REQUEST, "数据库中已存在该记录");
	}

	/**
	 * 没有权限
	 *
	 * @param e
	 * @return cn.iclass.common.utils.R
	 * @author alan
	 * @date 2019/6/10 5:34 PM
	 */
	@ExceptionHandler(AuthorizationException.class)
	public Result handleAuthorizationException(AuthorizationException e) {
		log.warn("没有权限:{}", e.getMessage());
		return Result.error(HttpStatus.SC_UNAUTHORIZED, "没有权限，请联系管理员授权");
	}

	/**
	 * handleError
	 *
	 * @param ex
	 * @return cn.iclass.common.utils.R
	 * @author alan
	 * @date 2019/9/11 09:58
	 */
	@ExceptionHandler(MissingServletRequestParameterException.class)
	public Result handleMissingServletRequestParameterException(MissingServletRequestParameterException ex) {
		log.warn("缺少请求参数:{}", ex.getMessage());
		String message = String.format("缺少必要的请求参数: %s", ex.getParameterName());
		return Result.error(HttpStatus.SC_BAD_REQUEST, message);
	}

	/**
	 * handleError
	 *
	 * @param ex
	 * @return cn.iclass.common.utils.R
	 * @author alan
	 * @date 2019/9/11 09:58
	 */
	@ExceptionHandler(MethodArgumentTypeMismatchException.class)
	public Result handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException ex) {
		log.warn("请求参数格式错误:{}", ex.getMessage());
		String message = String.format("请求参数格式错误: %s", ex.getName());
		return Result.error(HttpStatus.SC_BAD_REQUEST, message);
	}

	/**
	 * 参数必填校验
	 *
	 * @param ex
	 * @return
	 */
	@ExceptionHandler({MethodArgumentNotValidException.class})
	public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
		log.warn("参数必填校验:{}", ex.getMessage());
		List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();
		StringBuilder sb = new StringBuilder();
		for (FieldError fieldError : fieldErrors) {
			sb.append(fieldError.getDefaultMessage()).append(";");
		}
		// 生成返回结果
		return Result.error(HttpStatus.SC_BAD_REQUEST, sb.toString());
	}

	/**
	 * 参数必填校验
	 *
	 * @param ex
	 * @return
	 */
	@ExceptionHandler({BindException.class})
	public Result handleBindException(BindException ex) {
		log.warn("参数必填校验:{}", ex.getMessage());
		List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();
		StringBuilder sb = new StringBuilder();
		for (FieldError fieldError : fieldErrors) {
			sb.append(fieldError.getDefaultMessage()).append(";");
		}
		// 生成返回结果
		return Result.error(HttpStatus.SC_BAD_REQUEST, sb.toString());
	}

	/**
	 * 全局异常
	 *
	 * @param e
	 * @return cn.iclass.common.utils.R
	 * @author alan
	 * @date 2019/6/10 5:35 PM
	 */
	@ExceptionHandler(Exception.class)
	public Result handleException(Exception e) {
		log.error(e.getMessage(), e);
		return Result.error();
	}
}
